﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using mshtml;

namespace SpicIE.Parameter
{
    /// <summary>
    /// Class containing all adopted properties from the HTMLDocument
    /// </summary>
    [CLSCompliant(false)]
    public class Document
    {
        protected static HTMLDocument browserDocument;

        /// <summary>
        /// Global document constructor
        /// </summary>
        /// <param name="doc"></param>
        public Document(HTMLDocument doc)
        {
            browserDocument = doc;
        }

        /// <summary>
        /// Gets or sets the title for the current html document
        /// </summary>
        public string Title
        {
            get
            {
                return (browserDocument != null) ? browserDocument.title : string.Empty;
            }
            set
            {
                browserDocument.title = value;
            }
        }

        /// <summary>
        /// Gets or sets the URL for the current html document
        /// </summary>
        public string URL
        {
            get
            {
                return (browserDocument != null) ? browserDocument.url : string.Empty;
            }
            set
            {
                browserDocument.url = value;
            }
        }

        /// <summary>
        /// Gets or sets the baseURL for the current html document
        /// </summary>
        public string BaseUrl
        {
            get
            {
                return (browserDocument != null) ? browserDocument.baseUrl : string.Empty;
            }
            set
            {
                browserDocument.baseUrl = value;
            }
        }

        /// <summary>
        /// Gets or sets the charSet for the current html document
        /// </summary>
        public string CharSet
        {
            get
            {
                return (browserDocument != null) ? browserDocument.charset : string.Empty;
            }
            set
            {
                browserDocument.charset = value;
            }
        }

        /// <summary>
        /// Gets or sets the default charSet for the current html document
        /// </summary>
        public string defaultCharSet
        {
            get
            {
                return (browserDocument != null) ? browserDocument.defaultCharset : string.Empty;
            }
            set
            {
                browserDocument.defaultCharset = value;
            }
        }

        /// <summary>
        /// Retrieves or sets a cookie corrosponding to the value
        /// </summary>
        public string Cookie
        {
            get
            {
                return (browserDocument != null) ? browserDocument.cookie : string.Empty;
            }
            set
            {
                browserDocument.cookie = value;
            }
        }

        /// <summary>
        /// Gets the filesize for the current document
        /// </summary>
        public string FileSize
        {
            get
            {
                return (browserDocument != null) ? browserDocument.fileSize : string.Empty;
            }
        }

        /// <summary>
        /// Gets the date the current document was created
        /// </summary>
        public string FileCreatedDate
        {
            get
            {
                return (browserDocument != null) ? browserDocument.fileCreatedDate : string.Empty;
            }
        }

        /// <summary>
        /// Retrieves the protocol for the current document
        /// </summary>
        public string Protocol
        {
            get
            {
                return (browserDocument != null) ? browserDocument.protocol : string.Empty;
            }
        }

        /// <summary>
        /// Gets the readyState for the current document
        /// </summary>
        public string ReadyState
        {
            get
            {
                return (browserDocument != null) ? browserDocument.readyState : string.Empty;
            }
        }

        /// <summary>
        /// Retrieves a collection of links on the current html document
        /// </summary>
        public IEnumerable<string> LinkCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.links;

                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLAnchorElement item = (HTMLAnchorElement)ienum.Current;
                        results.Add(item.outerHTML);
                    }
                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.LinksCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of images on the current html document
        /// </summary>
        public IEnumerable<string> ImageCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.images;
                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLImg item = (HTMLImg)ienum.Current;
                        results.Add(item.outerHTML);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.ImageCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of anchors on the current html document
        /// </summary>
        public IEnumerable<string> AnchorCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.anchors;
                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLAnchorElement item = (HTMLAnchorElement)ienum.Current;
                        results.Add(item.outerHTML);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.AnchorCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of applets on the current html document
        /// </summary>
        public IEnumerable<string> AppletCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.applets;
                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLObjectElement item = (HTMLObjectElement)ienum.Current;
                        results.Add(item.outerHTML);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.AppletCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of embeds on the current html document
        /// </summary>
        public IEnumerable<string> EmbedCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.embeds;
                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLEmbed item = (HTMLEmbed)ienum.Current;
                        results.Add(item.outerHTML);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.EmbedCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of forms on the current html document
        /// </summary>
        public IEnumerable<string> FormCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.forms;
                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLFormElement item = (HTMLFormElement)ienum.Current;
                        results.Add(item.outerHTML);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.FormCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of frames on the current html document
        /// </summary>
        public IEnumerable<Document> FrameCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<Document> results = new List<Document>();

                    FramesCollection col = browserDocument.frames;
                    for (int i = 0; i < col.length; i++)
                    {
                        object num = i;
                        HTMLWindow2 item = (HTMLWindow2)col.item(ref num);
                        Document doc = new Document(item.document as HTMLDocument);
                        results.Add(doc);
                    }
                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.FramesCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of plugins on the current html document
        /// </summary>
        public IEnumerable<string> PluginCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.plugins;
                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLEmbed item = (HTMLEmbed)ienum.Current;
                        results.Add(item.outerHTML);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.PluginCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of scripts on the current html document
        /// </summary>
        public IEnumerable<string> ScriptCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElementCollection col = browserDocument.scripts;
                    IEnumerator ienum = col.GetEnumerator();
                    while (ienum.MoveNext())
                    {
                        HTMLScriptElement item = (HTMLScriptElement)ienum.Current;
                        results.Add(item.outerHTML);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.ScriptCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves a collection of stylesheets on the current html document
        /// </summary>
        public IEnumerable<string> StyleSheetCollection
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    foreach (IHTMLStyleSheet styleSheet in browserDocument.styleSheets)
                    {
                        results.Add(styleSheet.cssText);
                    }

                    return results;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.StyleSheetCollection, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Returns the active element of the document
        /// </summary>
        [CLSCompliant(false)]
        public IHTMLElement ActiveElement
        {
            get
            {
                try
                {
                    if (browserDocument == null)
                        return null;

                    List<string> results = new List<string>();

                    IHTMLElement item = browserDocument.activeElement;

                    return item;
                }
                catch (Exception ex)
                {
                    SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Document.activeElement, error in invoke: " + ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Retrieves the body of the document
        /// </summary>
        public string Body
        {
            get
            {
                if (browserDocument != null)
                {
                    HTMLBody body = (HTMLBody)browserDocument.body;
                    return body.outerHTML;
                }
                else
                {
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// Gets or sets the background-color for the current document
        /// </summary>
        public string BackgroundColor
        {
            get
            {
                return (browserDocument != null) ? (string)browserDocument.bgColor : null;
            }
            set
            {
                browserDocument.bgColor = value;
            }
        }

        /// <summary>
        /// Gets or sets the foreground-color for the current document
        /// </summary>
        public string ForegroundColor
        {
            get
            {
                return (browserDocument != null) ? (string)browserDocument.fgColor : null;
            }
            set
            {
                browserDocument.fgColor = value;
            }
        }

        /// <summary>
        /// enables or disables the download ability
        /// </summary>
        public bool EnableDownload
        {
            get
            {
                return (browserDocument != null) ? browserDocument.enableDownload : true;
            }
            set
            {
                browserDocument.enableDownload = value;
            }
        }
    }
}
